package com.bardsoftware.foronuvolo.data;

import static com.bardsoftware.foronuvolo.data.CollectionsUtil.first;
import java.io.Serializable;
import java.text.MessageFormat;
import java.util.Date;
import java.util.List;
import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;


import com.bardsoftware.foronuvolo.client.Urls;
import com.bardsoftware.foronuvolo.server.ForoNuvoloConstants;
import com.bardsoftware.foronuvolo.server.MessageCache;
import com.bardsoftware.foronuvolo.server.WikiMessageFormatter;
import com.google.appengine.api.datastore.Key;
import com.google.gdata.util.common.base.CharEscapers;
import com.google.gdata.util.common.base.Pair;
import com.google.gdata.util.common.base.StringUtil;

public class DiscussionsViewItem implements Serializable {
    private static final Pattern TITLE = Pattern.compile("^(\\s*=)([^=]+)(=\\s*)$");
    private final String username;
    private final Date startDate;
    private final String viewLink;
    private final int replyCount;
    private final String text;
    private final Boolean truncated;
    private final String myRefID;
    private final String myTitle;
    private final Date lastUpdateDate;
    private final String lastUpdateUsername;

    public DiscussionsViewItem(Discussion d, MessageCache<Key, Pair<String, Boolean>> messageTextCache, WikiMessageFormatter formatter) {
        List<Message> sortedMessages = d.getSortedMessages();
        final Message message = first(sortedMessages);
        this.replyCount = d.getReplyCount();
        this.startDate = message.getCreation();
        this.viewLink = ForoNuvoloConstants.ANSWERS_VIEW_PATH + d.getCreationOrder() + "#" + replyCount;
        this.username = message.getUserDisplayName();
        this.myRefID = d.getCreationOrder();

        Pair<String, Boolean> cachedText = messageTextCache.get(message.getID());
        if (false && cachedText != null) {
            this.text = cachedText.getFirst();
            this.truncated = cachedText.getSecond();
            int posTitle = this.text.indexOf("<a class=titlelink");
            if (posTitle >= 0) {
                int posTitleStart = this.text.indexOf("\">", posTitle);
                int posTitleEnd = this.text.indexOf("</a>", posTitleStart);
                myTitle = this.text.substring(posTitleStart + 2, posTitleEnd);
            } else {
                myTitle = "";
            }
        } else {
            String rawText = message.isTrusted() ? message.getText() : CharEscapers.htmlEscaper().escape(message.getText());
            String titlePattern = "<a class=titlelink href=\"" + viewLink + "\">{0}</a>";
            FormattedText formattedText = format(rawText, formatter, titlePattern);
            if ("20110513191700_s1hrcg54aqgzatd3dfvvybtj".equals(d.getCreationOrder())) {
                Logger.getLogger(Logger.GLOBAL_LOGGER_NAME).warning("raw=" + rawText + " formatted=" + formattedText.text);
            }
            this.myTitle = formattedText.title;
            this.text = formattedText.text;
            this.truncated = formattedText.isTruncated;
            messageTextCache.put(
                    message.getID(),
                    new Pair<String, Boolean>(this.text, formattedText.isTruncated));
        }

        if (sortedMessages.size() <= 1) {
            this.lastUpdateDate = null;
            this.lastUpdateUsername = null;
        } else {
            Message lastMessage = sortedMessages.get(sortedMessages.size()-1);
            this.lastUpdateDate = lastMessage.getCreation();
            this.lastUpdateUsername = lastMessage.getUserDisplayName();
        }
    }

    public static class FormattedText {
        public final String title;
        public final String text;
        public final boolean isTruncated;

        FormattedText(String title, String text, boolean truncated) {
            this.title = title;
            this.text = text;
            this.isTruncated = truncated;
        }
    }

    public static FormattedText format(String rawText, WikiMessageFormatter formatter, String titlePattern) {
        String title = "";
        int posLinebreak = rawText.indexOf('\n');
        if (posLinebreak >= 0) {
            String firstLine = rawText.substring(0, posLinebreak);
            Matcher matcher = TITLE.matcher(firstLine);
            if (matcher.find()) {
                title = matcher.group(2);
                rawText = matcher.group(1)
                    + MessageFormat.format(titlePattern, title)
                    + matcher.group(3)
                    + rawText.substring(posLinebreak);
            }
        }

        WikiMessageFormatter.Result r = formatter.format(rawText);
        String tmpText = r.text;
        for (String stripped = StringUtil.stripSuffix(tmpText, "<br>");
             stripped != null && stripped.length() < tmpText.length();
             stripped = StringUtil.stripSuffix(tmpText, "<br>")) {
             tmpText = stripped;
        }
        return new FormattedText(title, tmpText, r.isTruncated);
    }


    public String getUsername() {
        return username;
    }
    public Date getStartDate() {
        return startDate;
    }
    public String getViewLink() {
        return viewLink;
    }
    public int getReplyCount() {
        return replyCount;
    }
    public String getText() {
        return text;
    }
    public boolean getTruncated() {
        return truncated;
    }

    public static String getRefIDFromViewPath(String path) {
        return Urls.getDiscussionRefIDFromViewPath(path);
    }

    public String getRefID() {
        return myRefID;
    }

    public String getTitle() {
        return myTitle;
    }

    public boolean getLastUpdate() {
        return this.lastUpdateDate != null;
    }

    public Date getLastUpdateDate() {
        return this.lastUpdateDate;
    }

    public String getLastUpdateUsername() {
        return this.lastUpdateUsername;
    }
}
